﻿#include "ManageProxy.h"
#include "TapData.h"
#include "DataCache.h"
#include "compress.h"
#include "DataForward.h"
#include "configure.h"
#include "VethData.h"
#include "MacType.h"
#include "FlowController.h"
#include "proxyEncrypt.h"

#ifdef PROXYENCRYPT
#include "VVSec_smapi.h"
#include "securev2v_smapi.h"
#endif

#define  _LOG_MANAGEPROXY_DEBUG(_id,_format,...)  SLT_LOG_DEBUG("[mgproxy](%u)" _format,_id, ##__VA_ARGS__)
#define  _LOG_MANAGEPROXY_INFO(_id,_format,...)  SLT_LOG_INFO("[mgproxy](%u)" _format,_id, ##__VA_ARGS__)
#define  _LOG_MANAGEPROXY_ERR(_id,_format,...)  SLT_LOG_ERR("[mgproxy](%u)" _format,_id, ##__VA_ARGS__)

/* 关于加解密失败发起协商的几种情况
1、加密失败，存在父级向父级协商，不存在数据丢弃
2、解密失败、
        1）、如果是父级发来的消息，自己和父级协商。
        2）、如果不是父亲发来的消息，反馈解密失败，并且自己去和父亲协商
*/

void VirInterfaceAdpt::setRecvCB(std::function<void (VirInterfaceAdpt *p,DataCache &data)> _fun)
{
    m_cb_fun = _fun;
}
void VirInterfaceAdpt::VRecvData(DataCache data)
{
    if(m_cb_fun){
        m_cb_fun(this,data);
    }
}

typedef  std::lock_guard<std::mutex>  locker;

ManageProxy::ManageProxy()
{
    //虚拟网卡
    for(auto &item:configure::instance()->m_config.virtuals){
        VirInterfaceAdptSptr vfa = std::make_shared<VirInterfaceAdpt>();
        
        if (1 == item.virtual_type)
        {
            // m_vir_handler = TapDataPtr(new TapData(
            //     configure::instance()->get_vir_mac(), std::bind(&ManageProxy::VRecvData, this, std::placeholders::_1)
            // ));
            vfa->m_vir_handler =  TapDataPtr(new TapData(
                item.virtual_mac2, std::bind(&VirInterfaceAdpt::VRecvData, vfa.get(), std::placeholders::_1)
            ));
        }
        else
        {
            // m_vir_handler = VethDataPtr(new VethData(
            //     configure::instance()->get_vir_mac(), std::bind(&ManageProxy::VRecvData, this, std::placeholders::_1)
            // ));
            vfa->m_vir_handler = VethDataPtr(new VethData(
                item.virtual_mac2, std::bind(&VirInterfaceAdpt::VRecvData, vfa.get(), std::placeholders::_1)
            ));
        }

        vfa->setRecvCB(std::bind(&ManageProxy::VRecvData2,this,std::placeholders::_1,std::placeholders::_2));
        vfa->m_encrypt = item.encrypt;
        vfa->m_localIP = item.virtual_ip;
        //LOGFMTE("load config,m_localIP:%s,virtual_ip:%s",vfa->m_localIP.c_str(),item.virtual_ip.c_str());
        vfa->m_localName = item.virtual_name1;
        vfa->m_localMac = MacType((const unsigned char*)item.virtual_mac1.c_str(),1);
        m_vir_handlerMap.insert(std::make_pair(vfa->m_localMac,vfa));
        //LOGFMTE("load config,add vmac:%s, configmac:%s",vfa->m_localMac.toString().c_str(),item.virtual_mac1.c_str());
    }
    m_flow_control = FlowControllerPtr(new FlowController("monitor", 3000));
    //物理网卡
    m_dataforw = DataForwardPtr(
        new DataForward(configure::instance()->get_phy_mac(), RawType::QTXSOCKET)
    );
    //arp协议
    m_vir_table.insert(
        { {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, {"0.0.0.0", {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}} }
    );

    m_encrypt = configure::instance()->get_encrypt();
    m_startup = 0;
}

ManageProxy::~ManageProxy()
{
    shutdown();
}

int ManageProxy::init()
{
    if ("" != configure::instance()->m_config.up_mac)
    {
        int tempValue[6] = { 0 }, ret = 0;
        if (6 != (ret = sscanf(configure::instance()->m_config.up_mac.c_str(), "%02x:%02x:%02x:%02x:%02x:%02x",
            &tempValue[0], &tempValue[1], &tempValue[2], &tempValue[3], &tempValue[4], &tempValue[5]
        )))
        {
            LOGFMTE("failed to parse up mac : %s, up mac is null", configure::instance()->m_config.up_mac.c_str());
        }
        for (uint8_t i = 0; i < 6; ++i) m_parent_mac[i] = tempValue[i];
    }

    //虚拟网卡初始化
    for(auto &vitem : m_vir_handlerMap){
        if (0 != vitem.second->m_vir_handler->init())
        {
            vitem.second->m_vir_handler.reset();
            _LOG_MANAGEPROXY_ERR(0,"m_vir_handler init error:%s",vitem.second->m_localMac.toString().c_str());
            return -1;
        }
    }

    if (0 != m_flow_control->start())
    {
        for(auto &vitem : m_vir_handlerMap){
            vitem.second->m_vir_handler.reset();
        }
        m_flow_control.reset();
        _LOG_MANAGEPROXY_ERR(0,"m_flow_control init error");
        return -1;
    }
    //物理网卡初始化
    if (0 != m_dataforw->init())
    {
        for(auto &vitem : m_vir_handlerMap){
            vitem.second->m_vir_handler.reset();
        }
        m_dataforw.reset();
        m_flow_control.reset();
        _LOG_MANAGEPROXY_ERR(0,"m_dataforw init error");
        return -1;
    }
    m_startup = 1;

    m_dataforw->VSubscribe(
        TYPE_LAN_IN_ENRYPT_DATA, std::bind(&ManageProxy::NRecvData, this, TYPE_LAN_IN_ENRYPT_DATA, std::placeholders::_1, std::placeholders::_2)
    );
    m_dataforw->VSubscribe(
        TYPE_LAN_IN_DATA, std::bind(&ManageProxy::NRecvData, this, TYPE_LAN_IN_DATA, std::placeholders::_1, std::placeholders::_2)
    );
    m_dataforw->VSubscribe(
        TYPE_LAN_ARP, std::bind(&ManageProxy::ArpProcess, this, std::placeholders::_1, std::placeholders::_2)
    );
    //m_dataforw->VSubscribe(
    //    TYPE_LAN_IN_ENRYPT_DATA, std::bind(&ManageProxy::DecryptError, this, std::placeholders::_1, std::placeholders::_2)
    //);
    /* 唤起协商密钥 */
     m_dataforw->VSubscribe(
        TYPE_LAN_IN_DECRYPT_ERR, std::bind(&ManageProxy::DecryptError, this, std::placeholders::_1, std::placeholders::_2)
    );

    m_thread_poll.push_back(
        new std::thread(std::bind(&ManageProxy::VirtualProcess, this))
    );
    m_thread_poll.push_back(
        new std::thread(std::bind(&ManageProxy::NicProcess, this))
    );

    return 0;
}

int ManageProxy::shutdown()
{
    m_startup = 0;
    for (auto& elem : m_thread_poll)
    {
        if (elem && elem->joinable()) elem->join();

        delete elem;
    }
    m_thread_poll.clear();

    if (m_dataforw) m_dataforw->shutdown();
    for(auto &vhitem:m_vir_handlerMap){
        vhitem.second->m_vir_handler->shutdown();
    }
    //if (m_vir_handler) m_vir_handler->shutdown();
    if (m_flow_control) m_flow_control->stop();

    return 0;
}

int ManageProxy::SendGeneralData(MacType mac, DataCache data)
{
    return SendAnyData(Type::TYPE_LAN_DATA, mac, std::move(data));
}

int ManageProxy::SendAnyData(Type type, MacType mac, DataCache data)
{
    if (!m_flow_control->SRecordFlow(data.size())) return -1;

    m_virdatapoll.Append({ mac, type, std::move(data) });

    return 0;
}

void ManageProxy::SubscribeData(std::function<void(MacType, DataCache)> func)
{
    m_dataforw->VSubscribe(Type::TYPE_LAN_DATA, func);
}

void ManageProxy::DecryptError(MacType mac, DataCache data)
{
    LOGFMTI("startGetKey recv data");
    CProxyEncryptManage::getInst()->startGetKey();
}

void ManageProxy::ArpProcess(MacType addr, DataCache data)
{
    char buff[20] = {0};
    if (NULL == data()) return;

    if (data.size() != (uint32_t)sizeof(ArpPack))
    {
        LOGFMTE("invalid apr data body");
        return;
    }
    //打印arpPack
    printArpPack(data,0,nullptr);
    ArpPack& aprbody = *((ArpPack*)data());

    sprintf(buff, "%u.%u.%u.%u", 
        aprbody.m_src_ip[0], aprbody.m_src_ip[1], aprbody.m_src_ip[2], aprbody.m_src_ip[3]
    );

    {/* 不存在创建，存在更新 */
        locker lock(m_mutex);
        std::pair<std::string, MacType>& elem = m_vir_table[aprbody.m_src];

        elem.first.assign(buff);
        elem.second = addr;
    }
    data.m_in_index = ++m_phy_index;
    m_nicdatapoll.Append(DataPack(addr, std::move(data)));
    
    LOGFMTE("update arp remote table info,index:%u, ip : %s, vir mac : %02x:%02x:%02x:%02x:%02x:%02x, nic mac : %02x:%02x:%02x:%02x:%02x:%02x,",
       data.m_in_index,
       buff, aprbody.m_src[0], aprbody.m_src[1], aprbody.m_src[2], aprbody.m_src[3], aprbody.m_src[4], aprbody.m_src[5],
       *(addr() + 0), *(addr() + 1), *(addr() + 2), *(addr() + 3), *(addr() + 4), *(addr() + 5)
    );
	// LOGFMTD("update arp table info, ip : %s, vir mac : %02x:%02x:%02x:%02x:%02x:%02x, nic mac : %02x:%02x:%02x:%02x:%02x:%02x",
    //     buff, aprbody.m_src[0], aprbody.m_src[1], aprbody.m_src[2], aprbody.m_src[3], aprbody.m_src[4], aprbody.m_src[5],
    //     *(addr() + 0), *(addr() + 1), *(addr() + 2), *(addr() + 3), *(addr() + 4), *(addr() + 5)
    // );
}

int ManageProxy::VirAnalysis(VirInterfaceAdpt *padpt,DataCache&& data)
{
    if (data.size() <= (int)sizeof(ether_header))
    {
        LOGFMTE("recv vir nic data error,lost : len : %d", data.size());
        dump_payload(data(), data.size());
        return 0;
    }
    

    uint16_t datatype = ntohs(*(uint16_t*)((data() + 12)));
    //多线程进入
    MacType remoteAddr;
    {
        locker   lock(m_mutex);
        //借用这个锁，保护序号赋值
        data.m_in_index = ++m_virtual_index;
        LOGFMTT("vir-nic recv data,type:%04X,local_vnic:%s ,remote_vnic:%s , index:%u,len:%d",
               (int)datatype,
               MacType(reinterpret_cast<const unsigned char*>(data()+6)).toString().c_str(),
               MacType(reinterpret_cast<const unsigned char*>(data())).toString().c_str(), data.m_in_index,data.size());

        auto iter = m_vir_table.find((unsigned char*)data());
        if (iter == m_vir_table.end())
        {
            LOGFMTW("no find dst mac : %02x:%02x:%02x:%02x:%02x:%02x",
                (uint8_t)data[0], (uint8_t)data[1], (uint8_t)data[2], (uint8_t)data[3], (uint8_t)data[4], (uint8_t)data[5]
            );
            return 0;
        }
        //else
            //LOGFMTD("find mac : %s", iter->second.second.toString().c_str());

        remoteAddr = iter->second.second;

        m_flow_control->SRecordFlow(data.size());
    }
    switch (datatype)
    {
    case ETHERTYPE_ARP:
        //打印arpPack
        printArpPack(data,1,padpt);
        datatype = Type::TYPE_LAN_ARP;
        break;
    case ETHERTYPE_IP:
        if(padpt->m_encrypt)
            datatype = Type::TYPE_LAN_IN_ENRYPT_DATA;
        else
            datatype = Type::TYPE_LAN_IN_DATA;
        break;
    default:
        LOGFMTE("invalid ethernet data : %02x", datatype);
        return -1;
    }
    padpt->m_recvVirCount++;
 
    if ((Type)datatype == Type::TYPE_LAN_IN_ENRYPT_DATA) /* 加密通道 */
    {
        //LOGFMTT("vir-nic recv data,EncodePack start,index:%u",data.m_in_index);
        DataCache enData = EncodePack(data);
        //LOGFMTT("vir-nic recv data,EncodePack end,index:%u",data.m_in_index);
        if (NULL == enData())
        {
            if (m_parent_mac != MacType()) 
            {
                LOGFMTI("encrypt fail, parent mac : %s, start create zgkey", m_parent_mac.toString().c_str());
                CProxyEncryptManage::getInst()->startGetKey();  /* 父级发来的 */
            }
            else
                LOGFMTI("encrypt fail, no find parent mac, wait create zgkey");
            return -1;
        }
        m_virdatapoll.Append({ remoteAddr, (Type)datatype, std::move(enData) });
    }
    else
        m_virdatapoll.Append({ remoteAddr, (Type)datatype, std::move(data) });

    return 0;
}

void ManageProxy::VRecvData(DataCache data)
{
    //废弃 使用VRecvData2
    // int size = m_virdatapoll.GetSize();
    
    // size = size >> 16;
    // if (size != 0)
    // {
    //     usleep(size);
    //     LOGFMTW("too much data in the (vir pool)receiving buffer, delay : %d(us)", size);
    // }

    // VirAnalysis(nullptr,std::move(data));
}
void ManageProxy::VRecvData2(VirInterfaceAdpt *p,DataCache &data)
{
    int size = m_virdatapoll.GetSize();
    
    size = size >> 16;
    if (size != 0)
    {
        usleep(size);
        LOGFMTW("vir-nic recv data,too much data in the (vir pool)receiving buffer, delay : %d(us)", size);
    }

    VirAnalysis(p,std::move(data));
}

void ManageProxy::NRecvData(Type type, MacType addr, DataCache data)
{
    int size = m_nicdatapoll.GetSize();

    size = size >> 16;
    if (size != 0)
    {
        usleep(size);
        LOGFMTW("phy-nic recv data,too much data in the (nic pool)receiving buffer, delay : %d(us)", size);
    }

    data.m_in_index = ++m_phy_index;
    LOGFMTT("phy-nic recv data,index:%u,remote_pnic:%s,local_vnic:%s,remote_vnic:%s,",
            data.m_in_index,addr.toString().c_str(),MacType(reinterpret_cast<const unsigned char*>(data())).toString().c_str(),MacType(reinterpret_cast<const unsigned char*>(data()+6)).toString().c_str());

    m_flow_control->RRecordFlow(data.size());  /* 记录接收流量 */
    m_nicdatapoll.Append(DataPack(addr, type, std::move(data))); 
}

void ManageProxy::VirtualProcess()
{
    while (m_startup)
    {
        DataPack data;

        if (!m_virdatapoll.RemoveHead(data, 1)) continue;

        //LOGFMTT("vir-nic recv data,to phy-nic start,index:%u",data.m_data.m_in_index);
        m_dataforw->SendDataByAddr(data.m_addr, data.m_type, std::move(data.m_data), 1000);
        //LOGFMTT("vir-nic recv data,to phy-nic end,index:%u",data.m_data.m_in_index);
    }
}

void ManageProxy::NicProcess()
{
    while (m_startup)
    {
        DataPack data;
        
        if (!m_nicdatapoll.RemoveHead(data, 1)) continue;
        //LOGFMTI("phy-nic recv data type:%04x",data.m_type);
        LOGFMTT("phy-nic recv data,to vir-nic start,index:%u,type:%04x,local_vnic:%s,remote_vnic:%s",
            data.m_data.m_in_index,data.m_type,
            MacType(reinterpret_cast<const unsigned char*>(data.m_data())).toString().c_str(),MacType(reinterpret_cast<const unsigned char*>(data.m_data()+6)).toString().c_str());
           
        if (data.m_type == Type::TYPE_LAN_IN_ENRYPT_DATA)
        {
            //LOGFMTT("phy-nic recv data,DecodePack start,index:%u",data.m_data.m_in_index);
            DataCache deData = DecodePack(data.m_data);
            //LOGFMTT("phy-nic recv data,DecodePack end,index:%u",data.m_data.m_in_index);
            if (NULL == deData()) {
                if (data.m_addr == m_parent_mac) {
                    LOGFMTI("recv parent info, decrypt fail, start create zgkey, parent : %s", m_parent_mac.toString().c_str());
                    CProxyEncryptManage::getInst()->startGetKey();  /* 父级发来的 */
                }
                else {
                    LOGFMTI("send to son, request create zgkey");
                    DataCache ec(5); ec.set(3);
                    SendAnyData(Type::TYPE_LAN_IN_DECRYPT_ERR, data.m_addr, std::move(ec));
                }
                continue;
            }

            //LOGFMTT("phy-nic recv data,to vir-nic start,index:%u",data.m_data.m_in_index);
            //m_vir_handler->VSendData(deData, 2000);
            //暂时没有找到mac信息，先广播吧,
            //data.m_addr
            // for(auto &vitem:m_vir_handlerMap){
            //     vitem.second->m_vir_handler->VSendData(deData,2000);
            // }
            auto vitemIter = m_vir_handlerMap.find((unsigned char*)deData());
            if(vitemIter != m_vir_handlerMap.end()){
                vitemIter->second->m_recvCount++;
                vitemIter->second->m_vir_handler->VSendData(deData,2000);
            }else{
                LOGFMTE("phy-nic recv data,to vir-nic start, find mac error:%s",MacType((unsigned char*)deData()).toString().c_str());
            }
            //LOGFMTT("phy-nic recv data,to vir-nic end,index:%u",data.m_data.m_in_index);
        }
        else{
            uint16_t datatype = ntohs(*(uint16_t*)((data.m_data() + 12)));
            // LOGFMTT("phy-nic recv data,to vir-nic start,index:%u,type:%04x,local_vnic:%s,remote_vnic:%s",
            // data.m_data.m_in_index,(int)datatype,
            // MacType(reinterpret_cast<const unsigned char*>(data.m_data())).toString().c_str(),MacType(reinterpret_cast<const unsigned char*>(data.m_data()+6)).toString().c_str());
            
            //if(ETHERTYPE_ARP == datatype){
            //if(MacType({0xff, 0xff, 0xff, 0xff, 0xff, 0xff}) == MacType((unsigned char*) data.m_data())){
            if((uint8_t)0xff == (uint8_t)data.m_data[0] && (uint8_t)0xff == (uint8_t)data.m_data[1] && (uint8_t)0xff == (uint8_t)data.m_data[2] 
                && (uint8_t)0xff == (uint8_t)data.m_data[3] && (uint8_t)0xff == (uint8_t)data.m_data[4] && (uint8_t)0xff == (uint8_t)data.m_data[5]){
                ArpPack& aprbody = *((ArpPack*) data.m_data());
                char buff[20] = {0};
                sprintf(buff, "%u.%u.%u.%u", 
                    aprbody.m_dst_ip[0], aprbody.m_dst_ip[1], aprbody.m_dst_ip[2], aprbody.m_dst_ip[3]
                );
                for(auto &vitem:m_vir_handlerMap){
                    LOGFMTT("phy-nic recv data,rec_ip:%s,m_ip:%s",buff,vitem.second->m_localIP.c_str());
                    if(strcmp(vitem.second->m_localIP.c_str(),buff)==0){
                        LOGFMTT("phy-nic recv data,to vir-nic start arp");
                        vitem.second->m_recvCount++;
                        vitem.second->m_vir_handler->VSendData(data.m_data,2000);
                    } 
                }
            }else{
                auto vitemIter = m_vir_handlerMap.find((unsigned char*)data.m_data());
                if(vitemIter != m_vir_handlerMap.end()){
                    vitemIter->second->m_recvCount++;
                    vitemIter->second->m_vir_handler->VSendData(data.m_data,2000);
                }else{
                    LOGFMTE("phy-nic recv data,to vir-nic start, find mac error:%s",MacType((unsigned char*)data.m_data()).toString().c_str());
                }
            }
           
        }
            
    }
}

DataCache ManageProxy::DecodePack(DataCache& _data)
{
    //数据解密
    if (_data() == nullptr){
        LOGFMTI("data is null");
        return DataCache();
    } 
    uint32_t result_len = _data.size() + 20;
    DataCache result(result_len);
    int ret = securev2v_symDecrypt(CProxyEncryptManage::getInst()->m_deviceHandle, 1, (uint8_t*)(_data()), (uint32_t)_data.size(), (uint8_t*)(result()), &result_len);
    if (0 != ret)
    {
        LOGFMTW("DecodePack error: %d",ret);
        return DataCache();
    }
    result.set(result_len);

    return result;
}

DataCache ManageProxy::EncodePack(DataCache& _data)
{
    //数据加密
    if (_data() == nullptr){
        LOGFMTW("data is null");
        return DataCache();
    }
    uint32_t result_len = _data.size() + 500;
    DataCache result(result_len);
    int ret = securev2v_symEncrypt(CProxyEncryptManage::getInst()->m_deviceHandle, 1, (uint8_t*)(_data()), (uint32_t)_data.size(), (uint8_t*)(result()), &result_len);
    if (0 != ret){
        LOGFMTW("EncodePack error: %d",ret);
        return DataCache();
    }
    result.set(result_len);

    return result;
}

void ManageProxy::showStatistics()
{
    for(auto &mItem:m_vir_handlerMap){
        SLT_LOG_WARM("[statistics] %s(send:%d,recv:%d)",mItem.second->m_localName.c_str(),mItem.second->m_recvVirCount,mItem.second->m_recvCount);
        mItem.second->m_recvVirCount = 0;
        mItem.second->m_recvCount = 0;
    }
    
}

void ManageProxy::printArpPack(DataCache &data,int type,VirInterfaceAdpt *padpt)
{
    char src_ip[20] = {0};
    char dst_ip[20] = {0};
    ArpPack& aprpack = *((ArpPack*)data());
    
    sprintf(src_ip, "%u.%u.%u.%u", 
        aprpack.m_src_ip[0], aprpack.m_src_ip[1], aprpack.m_src_ip[2], aprpack.m_src_ip[3]
    );
    sprintf(dst_ip, "%u.%u.%u.%u", 
        aprpack.m_dst_ip[0], aprpack.m_dst_ip[1], aprpack.m_dst_ip[2], aprpack.m_dst_ip[3]
    );
    if(type == 1){
        LOGFMT_DEBUG(0,"arp data %s type:%s m_dst_mac:%02x:%02x:%02x:%02x:%02x:%02x, m_src_mac :%02x:%02x:%02x:%02x:%02x:%02x, "
            "src_ip: %s, src_mac : %02x:%02x:%02x:%02x:%02x:%02x, dst_ip: %s,  dst_mac : %02x:%02x:%02x:%02x:%02x:%02x,"
            "arp.op:%d",
        padpt->m_localName.c_str(),
        (type==1) ? "send" : "accept",
        aprpack.m_dst_mac[0],aprpack.m_dst_mac[1],aprpack.m_dst_mac[2],aprpack.m_dst_mac[3],aprpack.m_dst_mac[4],aprpack.m_dst_mac[5],
        aprpack.m_src_mac[0],aprpack.m_src_mac[1],aprpack.m_src_mac[2],aprpack.m_src_mac[3],aprpack.m_src_mac[4],aprpack.m_src_mac[5],
        src_ip,
        aprpack.m_src[0], aprpack.m_src[1], aprpack.m_src[2], aprpack.m_src[3], aprpack.m_src[4], aprpack.m_src[5],
        dst_ip,
        aprpack.m_dst[0], aprpack.m_dst[1], aprpack.m_dst[2], aprpack.m_dst[3], aprpack.m_dst[4], aprpack.m_dst[5],
        (int)aprpack.m_op
        );
    }
    else{
        LOGFMT_DEBUG(0,"arp data type:%s m_dst_mac:%02x:%02x:%02x:%02x:%02x:%02x, m_src_mac :%02x:%02x:%02x:%02x:%02x:%02x, "
            "src_ip: %s, src_mac : %02x:%02x:%02x:%02x:%02x:%02x, dst_ip: %s,  dst_mac : %02x:%02x:%02x:%02x:%02x:%02x,"
            "arp.op:%d",
        (type==1) ? "send" : "accept",
        aprpack.m_dst_mac[0],aprpack.m_dst_mac[1],aprpack.m_dst_mac[2],aprpack.m_dst_mac[3],aprpack.m_dst_mac[4],aprpack.m_dst_mac[5],
        aprpack.m_src_mac[0],aprpack.m_src_mac[1],aprpack.m_src_mac[2],aprpack.m_src_mac[3],aprpack.m_src_mac[4],aprpack.m_src_mac[5],
        src_ip,
        aprpack.m_src[0], aprpack.m_src[1], aprpack.m_src[2], aprpack.m_src[3], aprpack.m_src[4], aprpack.m_src[5],
        dst_ip,
        aprpack.m_dst[0], aprpack.m_dst[1], aprpack.m_dst[2], aprpack.m_dst[3], aprpack.m_dst[4], aprpack.m_dst[5],
        (int)aprpack.m_op
        );
    }
    
}
